package org.bhf.jsp;

/**
 * Copyright (c) 2007, Blue Hole Software. All rights reserved.
 * Code licensed under the Apache 2.0 License:
 * http://www.apache.org/licenses/
 */

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;

import java.io.IOException;

/**
 * Renders an HTML <code>&lt;base&gt;</code> element with an href
 * attribute pointing to the invocation context. This
 * tag is only valid when nested inside a head tag body. The presence
 * of this tag allows the browser to resolve relative URL's to images,
 * CSS stylesheets  and other resources in a manner independent of the URL
 * used to invoke the <code>Page</code>.
 * @exclude
 */
public class BaseTag extends TagSupport
{
    private static final long serialVersionUID = -1676505332940116162L;

    /** The server name to use instead of request.getServerName(). */
    protected String server;

    /** The target window for this base reference. */
    protected String target;

    //
    // Properties
    //

    /**
     * Sets the target attribute.
     *
     * @param target The target attribute.
     */
    public void setTarget( final String target )
    {
        this.target = target;
    }

    /**
     * Sets the server attribute.
     *
     * @param server The server attribute.
     */
    public void setServer( final String server )
    {
        this.server = server;
    }

    /**
     * Process the start of this tag.
     *
     * @throws javax.servlet.jsp.JspException If a JSP exception has occurred.
     *
     * @return <code>Tag.EVAL_BODY_INCLUDE</code>.
     */
    @Override
    public int doStartTag() throws JspException
    {
        final HttpServletRequest    request     = (HttpServletRequest) pageContext.getRequest();
        final String                serverName  = (server == null) ? request.getServerName() : server;

        try
        {
            pageContext.getOut().write(
                renderBaseElement( request.getScheme(), serverName, request.getServerPort(), request.getContextPath() )
            );
        }
        catch( IOException e )
        {
            throw new JspException( e );
        }

        return Tag.EVAL_BODY_INCLUDE;
    }

    /**
     * Render a fully formed HTML &lt;base&gt; element and return it as a String.
     *
     * @param scheme     The scheme used in the url (ie. http or https).
     * @param serverName The name of the server (pass through attribute).
     * @param port       The port of the server (pass through attribute).
     * @param uri        The portion of the url from the protocol name up to the query
     *                   string.
     * @return String An HTML &lt;base&gt; element.
     */
    protected String renderBaseElement( final String scheme, final String serverName, final int port, final String uri )
    {
        final StringBuffer tag = new StringBuffer( "<base href=\"" );

        tag.append( TagUtils.createServerUriStringBuffer( scheme, serverName, port, uri ).toString() ).append( "/" );

        tag.append( "\"" );

        if( this.target != null )
        {
            tag.append( " target=\"" );
            tag.append( target );
            tag.append( "\"" );
        }
        // Tricky stuff between HTML, XML, and IE. This is not XHTML compliant!
        // TODO: is there an XHTML mode this should support?
        tag.append( "><!--[if IE]></base><![endif]-->" );

        return tag.toString();
    }
}